// 参考案例：http://zxt_team.gitee.io/qq-music-player/

// 处理 click 事件300ms延迟问题
FastClick.attach(document.body);

(async function () {
  /* 获取元素 */
  const baseBox = document.querySelector(".header-box .base"),
    playerButton = document.querySelector(".player-button"),
    wrapperBox = document.querySelector(".wrapper"),
    footerBox = document.querySelector(".footer-box"),
    currentBox = footerBox.querySelector(".current"),
    durationBox = footerBox.querySelector(".duration"),
    alreadyBox = footerBox.querySelector(".already"),
    markImageBox = document.querySelector(".mark-image"),
    loadingBox = document.querySelector(".loading-box"),
    audioBox = document.querySelector("#audioBox");
  let wrapperList = [], // 用于存储所有p标签
    timer = null, // 用来存储定时器
    matchCount = 0; // 用来记录歌词段落历史匹配的数量

  /* 音乐控制 */
  // format：时间格式化————把 秒数 转化为 多少分钟多少秒
  const format = function format(time) {
    let minutes = Math.floor(time / 60), // 秒数除以60，向下取整，得到分钟数
      seconds = Math.round(time - minutes * 60);

    // 小于10则补0，大于0则保证原来的数据是字符串
    minutes = minutes < 10 ? "0" + minutes : "" + minutes;
    seconds = seconds < 10 ? "0" + seconds : "" + seconds;
    return { minutes, seconds };
  };
  // playend：播放完毕后所要做的事
  const playend = function playend() {
    // 清除定时器
    clearInterval(timer);
    timer = null;
    // currentBox 里的文本改为 00:00
    currentBox.innerHTML = "00:00";
    // 进度条（绿色部分）的宽度改为0%
    alreadyBox.style.width = "0%";
    // 歌词回归原位
    wrapperBox.style.transform = "translateY(0)";
    // 歌词的选中样式移除
    wrapperList.forEach((item) => (item.className = ""));
    // 歌词段落历史匹配数量清零
    matchCount = 0;
    // playerButton的旋转动画移除
    playerButton.className = "play-button";
  };

  // handle：控制进度条和歌词移动
  const handle = function handle() {
    let pH = wrapperList[0].offsetHeight; // 获取每个p标签的高度
    // audio的属性：currentTime:当前播放的时间「单位秒」  duration:总时间
    let { currentTime, duration } = audioBox;
    // console.log(currentTime, duration);
    // 但凡 currentTime 和 duration 有一个是NaN，就不处理了
    if (isNaN(currentTime) || isNaN(duration)) return;
    // 执行时间格式化函数，解构出里面的minutes和seconds，并重命名
    let { minutes: currentTimeMinutes, seconds: currentTimeSeconds } =
        format(currentTime),
      { minutes: durationMinutes, seconds: durationSdeconds } =
        format(duration);

    // 如果播放结束：如果已经播放的时间>=总时间，说明已经播放完了，不必往下处理了
    if (currentTime >= duration) {
      playend();
      return;
    }
    // 动态控制 currentBox 和 durationBox 里的文本「分:秒」
    currentBox.innerHTML = `${currentTimeMinutes}:${currentTimeSeconds}`;
    durationBox.innerHTML = `${durationMinutes}:${durationSdeconds}`;

    // 控制进度条
    ratio = Math.round((currentTime / duration) * 100); // 「当前播放的时间」占「总时间」的比例，进行四舍五入
    alreadyBox.style.width = `${ratio}%`; // 进度条（绿色部分）的宽度，由 ratio 这个比例决定

    // 控制歌词
    let matchs = wrapperList.filter((item) => {
      let minutes = item.getAttribute("minutes"); // 获取p标签上存的属性minutes
      let seconds = item.getAttribute("seconds"); // 获取p标签上存的属性seconds
      // 返回和当前播放时间匹配的歌词段落
      return minutes === currentTimeMinutes && seconds === currentTimeSeconds;
    });
    // matchs的长度大于0，说明找到匹配的了
    if (matchs.length > 0) {
      // 让匹配的段落有 active 样式，而其余的移除 active 样式
      wrapperList.forEach((item) => {
        // 先让所有项的样式类都为空
        item.className = "";
      });
      // 给匹配的段落增加active样式类
      matchs.forEach((item) => (item.className = "active"));

      // 控制移动
      matchCount += matchs.length; // 历史匹配数量累加
      if (matchCount > 3) {
        // 历史匹配数量超过3个，wrapperBox就开始移动
        let offset = (matchCount - 3) * pH; // pH：wrapperList[0].offsetHeight：任意一个p标签的高度
        wrapperBox.style.transform = `translateY(${-offset}px)`;
      }
    }
  };

  // 点击按钮，音乐播放/暂停
  playerButton.addEventListener("click", function () {
    // paused为true，说明当前是暂停的————让其播放
    if (audioBox.paused) {
      audioBox.play();
      playerButton.className = "player-button move"; // 添加move样式类，这个样式类写了旋转动画
      handle(); // 在上方写一个方法handle，控制进度条和歌词移动
      if (!timer) timer = setInterval(handle, 1000); // 每隔一秒就执行一次handle，更新进度条和歌词移动
      return;
    }
    // paused为false，说明当前是播放的————让其暂停
    audioBox.pause();
    playerButton.className = "player-button"; // 移除move样式类，移除旋转动画
    clearInterval(timer); // 清除定时器
    timer = null;
  });

  /* 绑定数据 */
  // 绑定歌词的方法（单独抽出来）
  const bindLyric = function bindLyric(lyric) {
    // 解析歌词信息
    let arr = [];
    lyric.replace(/\[(\d+):(\d+).(?:\d+)\](.+)\n/g, (_, $1, $2, $3) => {
      arr.push({
        minutes: $1,
        seconds: $2,
        text: $3.trim(),
      });
    });
    // console.log(arr);

    // 歌词绑定
    let str = ``;
    arr.forEach(({ minutes, seconds, text }) => {
      str += `
      <p minutes="${minutes}" seconds="${seconds}">${text}</p>
      `;
    });
    wrapperBox.innerHTML = str;

    // 获取所有的p标签
    wrapperList = Array.from(wrapperBox.querySelectorAll("p")); // 获取wrapperBox下所有p标签并转化为数组
  };

  const binding = function binding(data) {
    let { title, author, duration, pic, audio, lyric } = data;

    // @1 绑定头部基本信息
    baseBox.innerHTML = `
    <div class="cover">
        <img src="${pic}" alt="" />
    </div>
    <div class="info">
        <h2 class="title">${title}</h2>
        <h3 class="author">${author}</h3>
    </div>
    `;

    // @2 绑定杂七杂八的信息
    durationBox.innerHTML = duration;
    markImageBox.style.backgroundImage = `url(${pic})`;
    audioBox.src = audio;

    // @3 绑定歌词信息
    bindLyric(lyric); // 在上方单独写一个方法

    // @4 关闭Loading效果
    loadingBox.style.display = "none";
  };

  // 向服务器发请求，从服务器获取相关的数据
  try {
    let { code, data } = await API.queryLyric();
    // 请求成功：网络层和业务层都成功
    if (+code === 0) {
      binding(data);
      return;
    }
  } catch (_) {}
  // 请求失败
  alert("网络繁忙，请刷新页面");
})();
